module reboot_c4(
		input	wire		sclk,
		input	wire		resetb,
		input	wire		clk_25M,
		input	wire		start,
		input	wire	[23:0]	reboot_addr,
		output	wire		busy
		);
		
		
reg	[21:0]	data_in;
reg	[2:0]	param;
reg		read_param;
reg	[1:0]	read_source;
reg		reconfig;
//wire		resetb==0='d0;
//wire		reset_timer='d0;
reg		write_param;
//wire		busy;
wire	[28:0]	data_out;
reg	[7:0]	state;
reg	[7:0]	next_state;
reg		en_error;
reg		start_t=0;
reg	[23:0]	reboot_addr_t;
reg	[1:0]	div_cnt=0;
reg		div_clk;
reg		div_sync;
reg		check_flag;
reg	[23:0]	lacth_addr;
reg	[4:0]	lacth_start;
reg	[2:0]	wait_cnt;

parameter	IDLE		=	8'b0000_0000;
parameter	W_CONFIG	=	8'b0000_0001;
parameter	WAIT_LOW	=	8'b0000_0010;
parameter	READ_CONFIG	=	8'b0000_0100;
parameter	CHECK_CON	=	8'b0000_1000;
parameter	W_WDOG		=	8'b0001_0000;
parameter	EN_WDOG		=	8'b0010_0000;
parameter	RECONFIG	=	8'b0100_0000;
parameter	ERROR	        =       8'b1000_0000;           

parameter	ACTIVE_PG_ADDR=22'h040000;
parameter	WDOW_VALUE=22'h000010;//valid 12bit lower 17bit is 17'b1000


always @(posedge clk_25M or negedge resetb)
	if(resetb==0)
		lacth_start<=0;
	else
		lacth_start<={lacth_start[3:0],start};
	
always @(posedge clk_25M or negedge resetb)
	if(resetb==0)
		lacth_addr<=0;
	else if(lacth_start[2:1]==2'b01)
		lacth_addr<=reboot_addr;

always @(posedge clk_25M or negedge resetb)
	if(resetb==0)
		wait_cnt<=0;
	else if(state!=WAIT_LOW)
		wait_cnt<=0;
	else if(wait_cnt[2]==1'd0)
		wait_cnt<=wait_cnt+1'd1;
		
//FSM
always @ (posedge clk_25M or negedge resetb)
	if(resetb==0)
		state<=IDLE;
	else
		case(state)
			IDLE:	
				if(lacth_start[4:3]==2'b01)
					state<=W_CONFIG;
			W_CONFIG:	
					state<=WAIT_LOW;
			READ_CONFIG:	
					state<=WAIT_LOW;
			CHECK_CON:
				if(en_error=='d1 && check_flag=='d1)
					state<=ERROR;
				else
					state<=W_WDOG;
			W_WDOG:	
				state<=WAIT_LOW;
			EN_WDOG:	
				state<=WAIT_LOW;
			RECONFIG:	
				state<=RECONFIG;//IDLE;
			ERROR:	
				state<=ERROR;
			WAIT_LOW:
			begin
				if(next_state==READ_CONFIG && !busy && wait_cnt[2]=='d1)
					state<=READ_CONFIG;
				else if(next_state==CHECK_CON  && !busy && wait_cnt[2]=='d1)
					state<=CHECK_CON;
				else if(next_state==EN_WDOG  && !busy && wait_cnt[2]=='d1)
					state<=EN_WDOG;
				else if(next_state==RECONFIG  && !busy && wait_cnt[2]=='d1)
					state<=RECONFIG;
			//else if(next_state==W_CONFIG && !busy)
				//state<=W_CONFIG;
				else 
					state<=WAIT_LOW;
			end
			default:
				state<=IDLE;
		endcase
//next_state
always @(posedge clk_25M or negedge resetb)
	if(resetb==0)
		next_state<=IDLE;
	else if(state == W_CONFIG)
			next_state<=READ_CONFIG;
		else if(state == READ_CONFIG)
			next_state<=CHECK_CON;
		else if(state == W_WDOG)
			next_state<=EN_WDOG;
		else if(state == EN_WDOG)
			next_state<=RECONFIG;
		//else if(state == RECONFIG)
			//next_state<=W_CONFIG;

//param
always @(posedge clk_25M or negedge resetb)
	if(resetb==0)
		param=3'b000;
	else if(state == W_CONFIG)
			param<=3'b100;
		else if(state == READ_CONFIG)
			param<=3'b111;
		else if(state == W_WDOG)
			param<=3'b010;
		else if(state == EN_WDOG)
			param<=3'b011;
		else param<=3'b000;
//read_source
always @ (posedge clk_25M or negedge resetb)
	if(resetb==0)
		read_source<=2'b00;
	else if(state == W_CONFIG)
			read_source<=2'b00;
		else if(state == READ_CONFIG)
			read_source<=2'b00;
		else if(state == W_WDOG)
			read_source<=2'b00;
		else if(state == EN_WDOG)
			read_source<=2'b00;
		else read_source<=2'b00;
//read_param
always @ (posedge clk_25M or negedge resetb)
	if(resetb==0)
		read_param<='b0;
	else if(state == READ_CONFIG)
			read_param<='b1;
		else read_param<='b0;
	
//write_param
always @(posedge clk_25M or negedge resetb)
	if(resetb==0)
		write_param<='b0;
	else if(state == W_CONFIG)
			write_param<='b1;
		else if(state == W_WDOG)
			write_param<='b1;
		else if(state == EN_WDOG)
			write_param<='b1;
		else write_param<='b0;
	
always @ (posedge clk_25M or negedge resetb)
	if(resetb==0)
		reconfig<='b0;
	else if(state == RECONFIG)
			reconfig<='b1;
		else reconfig<='b0;
	

//data_in
always @(posedge clk_25M or negedge resetb)
	if(resetb==0)
		data_in<='d0;		
	else if (state == W_CONFIG)
			data_in<={2'h0,lacth_addr[19:0]}>>2;//reboot_addr_t[19:0]}>>2;//ACTIVE_PG_ADDR;
		else if(state == W_WDOG)
			data_in<=WDOW_VALUE;
		else if(state == EN_WDOG)
			data_in<=22'h000001;
		else data_in<='d0;
	
always @(posedge clk_25M or negedge resetb)
	if(resetb==0)
		en_error<='b0;
	else if(state == CHECK_CON && data_out[4:0]==5'b00010)
			en_error<='b1;	//watchdog time out error
		else if(state == CHECK_CON && data_out[4:0]==5'b00100)
			en_error<='b1;//nSTATUS error
		else if(state == CHECK_CON && data_out[4:0]==5'b01000)
			en_error<='b1;//Configuration CRC error
		else if(state == CHECK_CON && data_out[4:0]==5'b10000)
			en_error<='b1;//external nCONFIG assertion
		else if(state == CHECK_CON && (data_out[4:0]==5'b00001 || data_out[4:0]==5'b00000 ))
			en_error<='b0;
		else 
			en_error<='b0;

always @(posedge clk_25M or negedge resetb)
	if(resetb==0)
		check_flag<='d0;
	else if(state == CHECK_CON)
		check_flag<='d1;
	else check_flag<='d0;
		
`ifdef BOOT_MODE
rsu_base	rsu_base_inst (
	.clock ( clk_25M ),
	.data_in ( data_in ),
	.param ( param ),
	.read_param ( read_param ),
	.read_source ( read_source ),
	.reconfig ( reconfig),
	.reset ( ~resetb),
	.reset_timer (  ~resetb ),
	.write_param ( write_param ),
	.busy ( busy ),
	.data_out ( data_out )
	);
`else
reg     [14:0]   reset_cnt;

always @(posedge sclk)
        if(start=='d0)
                reset_cnt<=reset_cnt+'d1;
		
rsu_base	rsu_base_inst (
	.clock ( ),
	.data_in ( ),
	.param (  ),
	.read_param ( ),
	.read_source (  ),
	.reconfig ( ),
	.reset ( ),
	.reset_timer ( reset_cnt[13] ),
	.write_param (  ),
	.busy ( busy ),
	.data_out (  )
	);
`endif

endmodule